package vip.lsjscl.flowboot.workflow.service;

import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import vip.lsjscl.flowboot.common.BusinessException;
import vip.lsjscl.flowboot.util.DKBeanUtil;
import vip.lsjscl.flowboot.util.constants.ActivityStatus;
import vip.lsjscl.flowboot.util.constants.ActivityType;
import vip.lsjscl.flowboot.util.constants.TransitionStatus;
import vip.lsjscl.flowboot.workflow.entity.DKActivity;
import vip.lsjscl.flowboot.workflow.entity.DKTransition;
import vip.lsjscl.flowboot.workflow.entity.DKWorkflowVersion;
import vip.lsjscl.flowboot.workflow.handler.DKConditionHandler;
import vip.lsjscl.flowboot.workflow.handler.DKTransitionHandler;
import vip.lsjscl.flowboot.workflow.model.Edge;
import vip.lsjscl.flowboot.workflow.repository.DKTransitionRepository;

import java.util.List;
import java.util.Map;

/**
 * 变迁
 *
 * @author zhangxingju
 * @date 2025/02/14
 */
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
@Service
public class DKTransitionService {
    private final ApplicationContext applicationContext;

    private final DKTransitionRepository transitionRepository;

    /**
     * 创建变迁关系
     */
    public void createTransition(Edge edge, DKWorkflowVersion version, String businessId, Map<String, DKActivity> activityMap) {
        DKActivity fromActivity = activityMap.get(edge.getSource());
        DKActivity toActivity = activityMap.get(edge.getTarget());

        if (fromActivity != null && toActivity != null) {
            DKTransition transition = new DKTransition();
            transition.setFromActivityName(fromActivity.getName());
            transition.setFromActivity(fromActivity);
            transition.setToActivityName(toActivity.getName());
            transition.setToActivity(toActivity);
            transition.setWorkflowVersionId(version.getId());
            transition.setBusinessId(businessId);
            if (fromActivity.getType() == ActivityType.start) {
                transition.setStatus(TransitionStatus.COMPLETED);
            }
            transition.setPriority(1);
            if (edge.getData() != null) {
                transition.setName(edge.getData().getName());
                transition.setCode(edge.getData().getCode());
                transition.setPriority(edge.getData().getPriority());
                transition.setConditionClass(edge.getData().getConditionClass());
                transition.setAfterClass(edge.getData().getAfterClass());
            }

            transitionRepository.save(transition);
        }
    }

    /**
     * 评估变迁条件
     */
    public boolean evaluateTransitionCondition(DKTransition transition) {
        String conditionClass = transition.getConditionClass();
        if (StringUtils.isBlank(conditionClass)) {
            return true;
        }
        try {
            Class<?> beanName = DKBeanUtil.getBeanName(conditionClass);
            DKConditionHandler handler = (DKConditionHandler) applicationContext.getBean(beanName);
            boolean evaluate = handler.evaluate(transition);
            if (evaluate) {
                executeTransitionAfterClass(transition);
            }
            return evaluate;
        }
        catch (Exception e) {
            throw new BusinessException("执行条件判断失败: " + e.getMessage());
        }
    }

    /**
     * 执行变迁后置处理
     */
    public void executeTransitionAfterClass(DKTransition transition) {
        if (transition != null && StringUtils.isNotBlank(transition.getAfterClass())) {
            try {
                Class<?> beanName = DKBeanUtil.getBeanName(transition.getAfterClass());
                DKTransitionHandler handler = (DKTransitionHandler) applicationContext.getBean(beanName);
                handler.handler(transition);
            }
            catch (Exception e) {
                throw new BusinessException("执行变迁后置处理失败: " + e.getMessage());
            }
        }
    }


    /**
     * 获取上一个活动节点
     * 通过查询所有以当前活动作为目标的变迁记录，返回对应的起始活动（假设只有一条记录）。
     *
     * @param currentActivity 当前活动
     * @param flag            是否为完成状态
     * @return 上一个活动节点，如果不存在则返回 null
     */
    public List<DKActivity> getFromActivity(DKActivity currentActivity, boolean flag) {
        List<DKTransition> transitions = transitionRepository.findAllByFromActivity(currentActivity);
        if (CollectionUtils.isEmpty(transitions)) {
            return null;
        }
        if (flag) {
            return transitions.stream().map(DKTransition::getFromActivity).filter(a -> a.getStatus() == ActivityStatus.COMPLETED).toList();
        }
        return transitions.stream().map(DKTransition::getFromActivity).toList();
    }

    /**
     * 激活变迁
     *
     * @param currentActivity 当前活动
     * @param nextActivity    下一个活动
     */
    public void activateTransition(DKActivity currentActivity, List<DKActivity> nextActivity) {
        //根据当前活动和下一个活动查询所有以当前活动为起点的变迁记录
        List<DKTransition> transitions = transitionRepository.findAllByFromActivityAndToActivityIn(currentActivity, nextActivity);
        for (DKTransition transition : transitions) {
            transition.setStatus(TransitionStatus.COMPLETED);
            transitionRepository.save(transition);
        }
    }

    /**
     * 获取所有入度变迁
     *
     * @param activity 活动节点
     * @return 入度变迁列表
     */
    public List<DKTransition> getIncomingTransitions(DKActivity activity) {
        return transitionRepository.findAllByToActivity(activity);
    }

    /**
     * 获取所有出度变迁
     *
     * @param activity 活动节点
     * @return 出度变迁列表
     */
    public List<DKTransition> getOutgoingTransitions(DKActivity activity) {
        return transitionRepository.findAllByFromActivity(activity);
    }
}